package cn.ltgodm.sandbox.utils;

import cn.ltgodm.sandbox.enums.ExecuteCodeStatusEnum;
import cn.ltgodm.sandbox.exception.CompliedException;
import cn.ltgodm.sandbox.exception.ExecuteException;
import cn.ltgodm.sandbox.exception.ProcessException;
import cn.ltgodm.sandbox.model.dto.ExecuteCodeResponse;
import cn.ltgodm.sandbox.model.dto.ExecuteMessage;
import cn.ltgodm.sandbox.model.dto.JudgeInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
 * @author ltgodm
 * @date 2024-03-07 12:07:33
 */
@Slf4j
public class ProcessUtil {

    /**
     * 获取执行信息
     * @param process 进程
     * @param optional 操作方式
     * @return 返回执行信息
     */
    public static ExecuteMessage getMessage(Process process,String optional) {
        ExecuteMessage executeMessage = new ExecuteMessage();
        int status;
        String msg;
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        try {
            status = process.waitFor();
            executeMessage.setExitValue(status);
        } catch (InterruptedException e) {
            throw new ProcessException(e.getMessage());
        }
        if (status == 0) {
            msg = getCmdInfo(process.getInputStream());
            executeMessage.setMessage(msg);
            log.error("{}成功：\n{}",optional,msg);
        } else {
            msg = getCmdInfo(process.getErrorStream());
            log.error("{}失败：\n{}",optional,msg);
            executeMessage.setErrorMessage(msg);
        }
        stopWatch.stop();
        long time = stopWatch.getLastTaskTimeMillis();
        executeMessage.setTime(time);
        //关闭资源
        process.destroy();
        return executeMessage;
    }

    /**
     * 获取输入流中的信息
     * @param inputStream 输入流
     * @return 返回值
     */
    private static String getCmdInfo(InputStream inputStream) {
        StringBuilder msg = new StringBuilder();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        while (true) {
            try {
                if (((line = bufferedReader.readLine()) == null)) break;
            } catch (IOException e) {
                throw new ExecuteException("执行异常");
            }
            msg.append(line);
        }
        //关闭资源
        try {
            inputStream.close();
        } catch (IOException e) {
            throw new ExecuteException("执行异常");
        }
        return msg.toString();
    }

    public static ExecuteCodeResponse getErrorResponse(Throwable e){
        Integer status;
        if (e instanceof CompliedException) {
            status = ExecuteCodeStatusEnum.COMPLITED_ERROR.getValue();
        }else if (e instanceof ProcessException){
            status = ExecuteCodeStatusEnum.USER_PROGRESS_ERROR.getValue();
        }else if (e instanceof ExecuteException) {
            status = ExecuteCodeStatusEnum.SANDBOX_ERROR.getValue();
        }else {
            status = ExecuteCodeStatusEnum.SANDBOX_ERROR.getValue();
        }
        return ExecuteCodeResponse
                .builder()
                .message(e.getMessage())
                .status(status)
                .outputList(new ArrayList<>())
                .judgeInfo(new JudgeInfo())
                .build();
    }
}
